#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define SIZE 512
#define SEP " \t\n" // 修改分隔符为空白字符，包括空格、制表符和换行符
#define NUM 32
#define ZERO '\0'

char* gArgv[NUM] = {NULL}; // 命令行参数表，必须以NULL结尾

const char* GetUsername() {
    const char* ret = getenv("USER");
    if (ret == NULL) {
        return "None";
    }
    return ret;
}

const char* GetHostname() {
    const char* ret = getenv("HOSTNAME");
    if (ret == NULL) {
        return "None";
    }
    return ret;
}

const char* GetCwd() {
    const char* ret = getenv("PWD");
    if (ret == NULL) {
        return "None";
    }
    return ret;
}

void MakeCommandAndPrint() {
    const char* username = GetUsername();
    const char* hostname = GetHostname();
    const char* cwd = GetCwd();
    char line[SIZE];
    snprintf(line, sizeof(line), "[%s@%s %s]>", username, hostname, strlen(cwd) == 1 ? "/" : cwd + 1);
    printf("%s", line);
    fflush(stdout);
}

int GetUserCommit(char commit[], size_t n) {
    const char* s = fgets(commit, n, stdin);
    if (s == NULL) {
        return -1;
    }
    commit[strcspn(commit, "\n")] = ZERO; // 移除末尾的换行符
    return strlen(commit);
}

void SplitCommit(char commit[], const char* sep) {
    int i = 0;
    char* token = strtok(commit, sep);
    while (token != NULL && i < NUM - 1) {
        gArgv[i++] = token;
        token = strtok(NULL, sep);
    }
    gArgv[i] = NULL; // 命令行参数表以NULL结尾
}

void ExecCommit() {
    pid_t id = fork();
    if (id == 0) {
        // 子进程
        execvp(gArgv[0], gArgv);
        exit(errno); // 执行失败时返回错误码
    } else if (id > 0) {
        // 父进程
        int status = 0;
        pid_t rid = waitpid(id, &status, 0);
        if (rid > 0) {
            if (WIFEXITED(status)) {
                int lastcode = WEXITSTATUS(status);
                if (lastcode != 0) {
                    printf("%s, %s\n", gArgv[0], strerror(lastcode));
                }
            } else {
                printf("exit_signal:%d\n", WTERMSIG(status));
            }
        } else {
            perror("waitpid");
        }
    } else {
        perror("fork");
    }
}

const char* GetHome() {
    const char* path = getenv("HOME");
    if (path == NULL) {
        return "/";
    }
    return path;
}

void Cd() 
{
    const char* path = gArgv[1]; // 获取目标路径
    if (path == NULL) 
        path = GetHome(); // 没有指定路径，默认为家目录

    // 切换目录
    if (chdir(path) != 0) {
        perror("chdir");
        return;
    }

    // 获取当前工作目录
    char cwd[SIZE];
    if (getcwd(cwd, sizeof(cwd)) == NULL) {
        perror("getcwd");
        return;
    }

    // 设置环境变量 PWD
    if (setenv("PWD", cwd, 1) != 0) {
        perror("setenv");
        return;
    }
}

//void Cd() {
//    const char* path = gArgv[1];
//    if (path == NULL) {
//        path = GetHome();
//    }
//    if (chdir(path) != 0) {
//        perror("chdir");
//    }
//    char temp[SIZE];
//    char cwd[SIZE];
//    if (getcwd(temp, sizeof(temp)) != NULL) {
//        snprintf(cwd, sizeof(cwd), "PWD=%s", temp);
//        putenv(cwd);
//    } else {
//        perror("getcwd");
//    }
//}

int CheckBuildin() {
    int yes = 0;
    if (strcmp(gArgv[0], "cd") == 0) {
        yes = 1;
        Cd();
    } else if (strcmp(gArgv[0], "echo") == 0 && gArgv[1] != NULL && strcmp(gArgv[1], "$?") == 0) {
        yes = 1;
        printf("%d\n", errno);
    }
    return yes;
}

int main() {
    int quit = 0;
    while (!quit) {
        MakeCommandAndPrint();
        char commit[SIZE];
        int ret = GetUserCommit(commit, sizeof(commit));
        if (ret == -1) {
            return -1;
        }
        SplitCommit(commit, SEP);
        ret = CheckBuildin();
        if (ret) {
            continue;
        }
        ExecCommit();
    }
    return 0;
}
